<template>
  <el-card>
    <PlusSearch
        v-model="searchParam"
        :columns="columnConfig"
        :show-number="3"
        :need-validate="true"
        @search="handleSearch"
        :defaultValues="defaultValues"
    />
  </el-card>
  <el-card style="margin-top: 4px">
    <!-- 先放汇总卡片（在筛选区上方，更符合看板逻辑） -->
    <div v-if="rawList.length > 0" class="summary-card">
      <h3>销量总览</h3>
      <div class="summary-stats">
        <div class="stat-item">
          <span class="stat-label">总销量</span>
          <span class="stat-value">{{ rawList.length }}</span>
          <span class="stat-unit">件</span>
        </div>
        <div class="stat-item">
          <span class="stat-label">涉及药品</span>
          <span class="stat-value">{{ medicineCount }}</span>
          <span class="stat-unit">种</span>
        </div>
        <div class="stat-item">
          <span class="stat-label">覆盖门店</span>
          <span class="stat-value">{{ storeCount }}</span>
          <span class="stat-unit">家</span>
        </div>
        <div class="stat-item">
          <span class="stat-label">销售代表</span>
          <span class="stat-value">{{ salesRepCount }}</span>
          <span class="stat-unit">人</span>
        </div>
      </div>
    </div>
    <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleTabClick">
      <el-tab-pane label="销售汇总" name="table">
        <SaleReport :raw-list="rawList"></SaleReport>
      </el-tab-pane>
      <el-tab-pane label="图表展示" name="echarts">
        <SaleChart :raw-list="rawList"></SaleChart>
      </el-tab-pane>
      <el-tab-pane label="汇总明细" name="detail">
        <SaleDetail :raw-list="rawList"></SaleDetail>
      </el-tab-pane>
    </el-tabs>
  </el-card>
</template>

<script setup lang="ts">
import {computed, onMounted, ref} from 'vue';
import type {SaleData, SaleQuery} from "../model/sale.ts";
import {type PlusColumn, PlusSearch} from "plus-pro-components";
import {useAuthStore} from "../stores/auth.ts";
import {commonQuery, type QueryCondition, type RangeFilter} from "../api/query.ts";
import type {TabsPaneContext} from 'element-plus'
import {formatDate} from "../utils/dateFormatter.ts";
import _ from 'lodash';
import SaleReport from "./SaleReport.vue";
import {addCascadeOptions} from "../model/common.ts";
import SaleDetail from "./SaleDetail.vue";
import {useBrandsStore} from "../stores/brand.ts";
import {useSalesRepsStore} from "../stores/sales_rep.ts";
import SaleChart from "./SaleChart.vue";
// 3. 绑定选中的分组维度（默认选中「销售代表」）
const selectedGroupKeys = ref(['sales_rep', 'medicine']);

// 5. 核心：按选中维度分组 + 汇总销量
const groupedData = computed(() => {
  const keys = selectedGroupKeys.value;
  if (keys.length === 0) return [];

  // 按选中的多个维度拼接唯一键（如「张三_阿莫西林_2025-11-01」）
  const grouped = _.groupBy(rawList.value, (item) => {
    return keys.map((key) => item[key]).join('_'); // 唯一键：维度值拼接
  });

  // 对每个分组汇总销量，保留分组字段
  return _.mapValues(grouped, (group) => {
    const base = _.pick(group[0], keys); // 保留所有分组字段
    return {
      ...base,
      sale_total: _.sumBy(group, 'sale_total'), // 汇总销量
    };
  });
});

// 6. 表格数据源：转数组 + 严格按分组维度排序（关键：保证同组连续）
const tableData = computed(() => {
  const data = _.values(groupedData.value);
  // 按选中的维度顺序排序（如先 sales_rep，再 medicine），确保同组数据挨在一起
  return _.sortBy(data, selectedGroupKeys.value);
});

// 7. 修复：计算每个分组维度的合并规则（核心修复点）
const spanRules = computed(() => {
  const data = tableData.value;
  const keys = selectedGroupKeys.value;
  const rules = {}; // 存储每个维度的合并规则：{ 字段名: [每行的合并行数] }

  // 为每个分组维度单独计算合并规则
  keys.forEach((key) => {
    const spans = [];
    if (data.length === 0) {
      rules[key] = spans;
      return;
    }

    let currentValue = data[0][key];
    let count = 1; // 连续相同值的行数

    for (let i = 1; i < data.length; i++) {
      // 判断当前行与上一行的「当前维度值」是否相同
      if (data[i][key] === currentValue) {
        count++;
      } else {
        spans.push(count); // 记录上一组的合并行数
        count = 1;
        currentValue = data[i][key];
      }

      // 最后一行补充剩余计数
      if (i === data.length - 1) {
        spans.push(count);
      }
    }

    rules[key] = spans;
  });

  return rules;
});

computed(() => {
  const data = tableData.value;
  const keys = selectedGroupKeys.value;
  const rules = spanRules.value;
  const result = []; // 最终格式：[ { 字段名: [行数, 列数] }, ... ]

  keys.forEach((key) => {
    const spans = rules[key];
    let spanIndex = 0; // 当前合并规则的索引
    let rowIndex = 0; // 当前行索引

    spans.forEach((span) => {
      // 该组有 span 行，仅第一行显示（[span, 1]），其余行隐藏（[0, 0]）
      for (let i = 0; i < span; i++) {
        if (!result[rowIndex + i]) {
          result[rowIndex + i] = {};
        }
        result[rowIndex + i][key] = i === 0 ? [span, 1] : [0, 0];
      }
      rowIndex += span;
      spanIndex++;
    });
  });

  return result;
});

const activeName = ref('table')

const handleTabClick = (tab: TabsPaneContext, event: Event) => {
  console.log(tab, event)
}

/**
 * 计算当前时间减去 24 小时的 Date 对象
 * @returns 昨天此时的 Date
 */
const getYesterday = (): Date => {
  const now = new Date(); // 当前时间（如 2025-11-08 14:30:00）
  const yesterdayTimestamp = now.getTime() - 24 * 60 * 60 * 1000; // 减去 24小时的毫秒数
  return new Date(yesterdayTimestamp); // 结果：2025-11-07 14:30:00
};
const getLastWeek = (): Date => {
  const now = new Date(); // 当前时间（如 2025-11-08 14:30:00）
  const yesterdayTimestamp = now.getTime() - 24 * 60 * 60 * 1000 * 7; // 减去 24小时的毫秒数
  return new Date(yesterdayTimestamp); // 结果：2025-11-07 14:30:00
};
/**
 * 获取本月第一天的 Date 对象（00:00:00.000）
 * @param timeZone 可选时区（如 'Asia/Shanghai'），默认使用本地时区
 * @returns 本月第一天的 Date 实例
 */
function getFirstDayOfCurrentMonth(timeZone?: string): Date {
  if (timeZone) {
    // 时区兼容版本（避免不同时区导致日期偏移）
    const now = new Date();
    // 构造 ISO 格式的当月第一天字符串（如 2024-10-01）
    const year = now.getFullYear();
    const month = now.getMonth() + 1; // 月份从 0 开始，需 +1
    const firstDayIso = `${year}-${month.toString().padStart(2, '0')}-01`;
    // 按指定时区解析为 Date（确保是该时区的 00:00）
    return new Date(firstDayIso + 'T00:00:00.000' + new Date().toTimeString().slice(8));
  }

  // 本地时区版本（简单场景）
  const date = new Date();
  date.setDate(1); // 设置日期为当月 1 号
  date.setHours(0, 0, 0, 0); // 重置时间为 00:00:00.000
  return date;
}
const startDateRef = ref<Date | null>(null);
const endDateRef = ref<Date | null>(null);
const yesterday = getYesterday()
const lastWeek = getLastWeek()

// 2. 在 onMounted 中初始化 Pinia 并读取状态（此时组件已挂载，Pinia 就绪）
onMounted(() => {
      const authStore = useAuthStore()
      const brandsStore = useBrandsStore()
      const salesRepsStore = useSalesRepsStore()
      salesRepsStore.sales_reps.forEach(item => {
        srOptions.value.push({
          label: item,
          value: item
        });
      })
      brandsStore.brands.forEach(item => {
        brandOptions.value.push({
          label: item.name,
          value: item.name
        });
      })
      startDateRef.value = yesterday;
      endDateRef.value = yesterday;
      // 读取 userInfo（此时状态已加载）
      const currentName = authStore.userInfo?.name;
      searchParam.value.sales_rep = (currentName && authStore.userInfo.role === 'sales_rep')
          ? [currentName]
          : []
      const defaultRegion = addCascadeOptions[0]
      searchParam.value.region = defaultRegion.children.map((item) => [defaultRegion.value, item.value])
    }
);

// 3. 调整 defaultValues 初始化（避免依赖未就绪的状态）
const defaultValues = {
  date_range: [getFirstDayOfCurrentMonth(), new Date()],
  sales_rep: [] as string[], // 初始为空数组，后续在 onMounted 中更新,
  region: [] as string[][],
};
const searchParam = ref({...defaultValues});
const brandOptions = ref([]);
const storeOptions = ref([]);
const srOptions = ref([]);
const rawList = ref<SaleData[]>([]); // 原始数据

// 5. computed计算属性（依赖响应式变量，放在变量后）
// 品牌选择器选项
const brandSelectOptions = computed(() => brandOptions.value);
const srSelectOptions = computed(() => srOptions.value);
const stSelectOptions = computed(() => storeOptions.value);
// 药品种类（去重）

const columnConfig: PlusColumn[] = [
  {
    label: '日期',
    // tooltip: '指定查询的日期范围',
    width: 120,
    prop: 'date_range',
    valueType: 'date-picker',
    fieldProps: {
      type: 'daterange',
      format: 'YYYY-MM-DD',
      startPlaceholder: "开始日期",
      endPlaceholder: "结束日期",
      defaultValue: [yesterday, yesterday],
      rangeSeparator: '~'
    },
    formProps: {
      validateOnRuleChange: true
    },
    tableColumnProps: {}
  },
  {
    label: '业务代表',
    width: 300,
    prop: 'sales_rep',
    valueType: 'select',
    options: srSelectOptions, // 这里依赖后面的 computed，没问题（computed 是响应式的）
    fieldProps: {
      multiple: true,
    }
  },
  {
    label: '品牌',
    // tooltip: '药店品牌',
    width: 60,
    prop: 'brand',
    tableColumnProps: {
      showOverflowTooltip: true
    },
    valueType: 'select',
    options: brandSelectOptions, // 这里依赖后面的 computed，没问题（computed 是响应式的）
    fieldProps: {
      multiple: true
    }
  },
  {
    label: '门店名称',
    width: 70,
    prop: 'store_name',
    valueType: 'select',
    options: stSelectOptions, // 这里依赖后面的 computed，没问题（computed 是响应式的）
    fieldProps: {
      multiple: true,
      filterable: true,
      remote: true,
      remoteMethod: async (query: string) => {
        if (query === '') {
          storeOptions.value = []
          return
        }
        const res = await commonQuery<any>('medicine_sale_summary', {
          fields: 'store_name',
          distinct: true,
          where: [
            {
              field: 'store_name',
              value: '%' + query + '%',
              operator: 'like'
            }
          ],
          order_by: [
            {
              field: 'sale_date',
              orderType: 'desc'
            },
            {
              field: 'brand',
            },
            {
              field: 'district',
            },
            {
              field: 'store_name',
            },
            {
              field: 'sale_total',
              orderType: 'desc'
            },
          ],
        });
        storeOptions.value = []
        res.forEach(sn => {
          storeOptions.value.push({label: sn.store_name, value: sn.store_name})
        })
      }
    },
  },
  {
    label: '区县',
    width: 100,
    prop: 'region',
    valueType: 'cascader',
    fieldProps: {
      props: {multiple: true},
      showAllLevels: false,
    },
    options: () => {
      return new Promise(resolve => {
        resolve(addCascadeOptions)
      })
    }
  },
];
const filterKey = ref<keyof SaleData | ''>('');
const filterValues = ref<string[]>([]);
// 筛选后的数据
const filteredData = computed<SaleData[]>(() => {
  return rawList.value.filter(item => {
    // 过滤字段筛选
    if (filterKey.value && filterValues.value.length > 0) {
      const itemValue = String(item[filterKey.value] ?? '未知');
      if (!filterValues.value.includes(itemValue)) return false;
    }
    return true;
  });
});
// 总销量汇总计算
let totalSaleCount = computed(() => {
  return filteredData.value.reduce((sum, item) => sum + (item.sale_total || 0), 0);
});
const medicineCount = computed(() => {
  return [...new Set(filteredData.value.map(item => item.medicine || '未知'))].length;
});
const storeCount = computed(() => {
  return [...new Set(filteredData.value.map(item => item.store_name || '未知'))].length;
});
const salesRepCount = computed(() => {
  return [...new Set(filteredData.value.map(item => item.sales_rep || '未知'))].length;
});

const getQueryDateRange = (saleQuery: SaleQuery): QueryCondition[] => {
  if (!saleQuery || !saleQuery.date_range || !saleQuery.date_range[0]) {
    return [];
  }
  const result: RangeFilter[] = [{
    field: 'sale_date', operator: '>=', value: formatDate(saleQuery.date_range[0])
  },]
  if (saleQuery.date_range[1]) {
    result.push({field: 'sale_date', operator: '<=', value: formatDate(saleQuery.date_range[1])})
  }
  return result
}

// 修复后的 getIns 函数：覆盖所有多选字段
const getIns = (saleQuery: SaleQuery): QueryCondition[] => {
  const res: QueryCondition[] = [];

  // 定义需要处理的多选字段映射（key：前端参数名，field：后端字段名）
  const multiSelectFields = [
    {paramKey: 'sales_rep', dbField: 'sales_rep'}, // 销售代表
    {paramKey: 'brand', dbField: 'brand'}, // 品牌（之前被忽略的字段）
    {paramKey: 'store_name', dbField: 'store_name'} // 门店（之前被忽略的字段）
  ];

  multiSelectFields.forEach(({paramKey, dbField}) => {
    // 1. 取出该字段的多选值（数组）
    const values = saleQuery[paramKey] as string[] | undefined;
    // 2. 过滤无效情况：值不存在、数组为空、只有空字符串
    if (!values || values.length === 0 || values.every(v => !v.trim())) {
      return;
    }
    // 3. 拼接 in 条件（去重，避免重复值）
    const uniqueValues = [...new Set(values)].filter(v => v.trim());
    if (uniqueValues.length > 0) {
      res.push({
        field: dbField,
        operator: 'in',
        value: uniqueValues
      });
    }
  });

  return res;
};

// 搜索按钮事件
const handleSearch = async (values: SaleQuery) => {
  let districts = values.region.map(r => r[1])
  // 只判断是否存在 null（排除空字符串、0 等其他 falsy 值）
  if (districts.some(v => v === null)) {
    districts.push('');
  }
  const res = await commonQuery<SaleData>('medicine_sale_summary', {

    format: [
      {field: 'sale_date', type: 'date', pattern: '2006-01-02'},
      {field: 'sale_total', type: 'number', pattern: '0'}
    ],
    distinct: true,
    where: [
      ...getQueryDateRange(values),
      ...getIns(values),
      {
        field: 'city',
        operator: 'in',
        value: _.uniq(
            _.map(values.region, _.head) as string[]// 先映射：获取每个子数组第一个元素
        )
      }, {
        field: 'district',
        operator: 'in',
        value: districts
      },],
    order_by: [
      {
        field: 'sale_date',
        orderType: 'desc'
      },
      {
        field: 'brand',
      },
      {
        field: 'district',
      },
      {
        field: 'store_name',
      },
      {
        field: 'sale_total',
        orderType: 'desc'
      },
    ],
  });
  // 转换sale_total为数字，处理可能的undefined
  rawList.value = res.map((item: any) => ({
    ...item,
    sale_total: item.sale_total ? Number(item.sale_total) : 0
  }));
};
</script>

<style scoped>
.container {
  padding: 16px; /* 增加内边距，避免内容贴边 */
}

label {
  font-weight: 500;
  color: #606266;
  white-space: nowrap;
}

.ml-6 {
  margin-left: 24px;
}

/* 汇总卡片样式优化 */
.summary-card {
  background: linear-gradient(135deg, #d3edf6 0%, #cdecf8 100%);
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.summary-card h3 {
  margin: 0 0 16px 0;
  color: #2d3748;
  font-size: 18px;
  font-weight: 600;
}

.summary-stats {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.stat-item {
  background: rgba(255, 255, 255, 0.8);
  padding: 16px 24px;
  border-radius: 8px;
  flex: 1;
  min-width: 120px;
  text-align: center;
}

.stat-label {
  display: block;
  font-size: 14px;
  color: #718096;
  margin-bottom: 4px;
}

.stat-value {
  font-size: 24px;
  font-weight: 700;
  color: #2d3748;
}

.stat-unit {
  font-size: 14px;
  color: #718096;
  margin-left: 4px;
}

/* 图表容器样式 */
.chart-container {
  margin-top: 20px;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  padding: 16px;
}

.empty-state {
  height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #909399;
}

/* 适配小屏幕 */
@media (max-width: 768px) {
  .filter-row {
    flex-direction: column;
    align-items: flex-start;
  }

  .ml-6 {
    margin-left: 0;
    margin-top: 16px;
  }

  :deep(el-select), :deep(el-date-picker) {
    width: 100%;
  }

  .summary-stats {
    flex-direction: column;
  }

  .stat-item {
    width: 100%;
  }
}

/* 可选：调整合计行样式 */
:deep(.el-table__footer-wrapper) {
  font-weight: bold;
  background-color: #fafafa;
}

/* 可选：调整合并单元格的边框样式 */
:deep(.el-table__cell) {
  border-right: 1px solid #e6e6e6 !important;
}
</style>